import logging
import requests


class JsonRpcClient:
    url = 'http://127.0.0.1:9099'
    db = 'DTCloud4'
    username = 'admin'
    password = 'admin'
    json_endpoint = f'{url}/jsonrpc'
    session_id = None

    @classmethod
    def _post_request(cls, data: dict) -> dict | None:
        try:
            response = requests.post(cls.json_endpoint, json=data)
            response.raise_for_status()
            json_response = response.json()
            if 'error' in json_response:
                logging.error(f"Error in response from Odoo: {json_response['error']}")
                return None
            return json_response
        except requests.RequestException as e:
            logging.error(f"Network or HTTP error occurred: {e}")
            return None
        except ValueError:
            logging.error("Invalid JSON response.")
            return None

    @classmethod
    def authenticate(cls):
        data = {
            "jsonrpc": "2.0",
            "method": "call",
            "params": {
                "service": "common",
                "method": "authenticate",
                "args": [cls.db, cls.username, cls.password, {}]
            },
            "id": None
        }
        result = cls._post_request(data)
        if result and 'result' in result:
            logging.info('Authentication successful')
            cls.session_id = result['result']
        elif result and 'error' in result:
            logging.error(f'Authentication Error: {result["error"]["data"]["message"]}')

    @classmethod
    def call_jsonrpc_method(cls, service: str, method: str, *args, **kwargs):
        if cls.session_id is None:
            cls.authenticate()

        rpc_args = [cls.db, cls.session_id, cls.password] + list(args)
        if kwargs:
            rpc_args.append(kwargs)

        data = {
            "jsonrpc": "2.0",
            "method": "call",
            "params": {
                "service": service,
                "method": method,
                "args": rpc_args
            },
            "id": None
        }
        result = cls._post_request(data)
        if result and 'result' in result:
            return result['result']
        elif result and 'error' in result:
            logging.error(f'Error calling DTCloud method: {result["error"]["data"]["message"]}')
            return None

    @classmethod
    def search(cls, model: str, domain: list = None, offset: int = None, limit: int = None, order: str = None):
        args = [domain or []]
        kwargs = {'offset': offset, 'limit': limit, 'order': order}
        kwargs = {k: v for k, v in kwargs.items() if v is not None}
        return cls.call_jsonrpc_method("object", "execute_kw", model, "search", args, kwargs)

    @classmethod
    def search_count(cls, model: str, domain: list = None, limit: int = None)-> int:
        args = [domain or []]
        kwargs = {'limit': limit}
        kwargs = {k: v for k, v in kwargs.items() if v is not None}
        return cls.call_jsonrpc_method("object", "execute_kw", model, "search_count", args, kwargs)

    @classmethod
    def browse(cls, model: str, ids=None):
        """
        :param model: str
        :param ids: list
        :return: 返回模型对象
        """
        return cls.call_jsonrpc_method("object", "execute", model, "browse", ids)

    @classmethod
    def create(cls, model: str, vals_list: list | dict) -> int | list[int]:
        return cls.call_jsonrpc_method("object", "execute_kw", model, "create", vals_list)

    @classmethod
    def write(cls, model: str, ids: list, vals: dict) -> bool:
        return cls.call_jsonrpc_method("object", "execute", model, "write", ids, vals)

    @classmethod
    def unlink(cls, model: str, ids: list) -> bool:
        return cls.call_jsonrpc_method("object", "execute_kw", model, "unlink", ids)


if __name__ == '__main__':
    env = JsonRpcClient()
    # print(odoo.search(model='res.users', domain=[("login", '=', 'admin')], limit=1, order='id desc'))
    # print(odoo.search_count(model='res.users', domain=[("login", '=', 'admin')], limit=1))
    #
    # a = odoo.browse(model='res.users', ids=[1])
    # print(a)
    # res_users = odoo.search(model='res.users', domain=[("login", '=', 'qy')], limit=1)
    # if res_users:
    #     odoo.unlink(model='res.users', ids=res_users)

    # res = odoo.create(model='res.users', vals_list=[{
    #     'name': 'QY',
    #     'login': 'qy'}])
    # print(res)

    res = env.search_count(model='res.users', domain=[("login", '=', 'qy123123')])
    print(res)
    # if res:
    #     odoo.unlink(model='res.users', ids=res)
    #     vals = {
    #         'name': 'QY1'
    #     }
    #     odoo.write(model='res.users', ids=res, vals=vals)
